package com.shanlitech.bluetooth.sample;

import android.content.Context;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import com.shanlitech.lbs.sample.*;

public class SampleDatabase {
    private static SampleDatabase instance;

    public static SampleDatabase getInstance(Context context) {
        if( instance == null ) {
            instance = new SampleDatabase(context);
        }
        return instance;
    }

    private final Context context;
    private final List<OneshotSample> oneshot = new ArrayList<>();
    private final List<RealtimeSample> realtime = new ArrayList<>();
    private final List<CalibrationSample> calibration = new ArrayList<>();

    private SampleDatabase(Context context) {
        this.context = context;
        refresh();
    }

    public void addOneshot(OneshotSample sample) {
        oneshot.add(sample);
    }

    public void addRealtime(RealtimeSample sample) {
        realtime.add(sample);
    }

    public void addCalibration(CalibrationSample sample) {
        calibration.add(sample);
    }

    public List<OneshotSample> getOneshot() {
        return oneshot;
    }

    public List<String> getOneshotNames() {
        final List<String> names = new ArrayList<>();
        for(OneshotSample s : oneshot) {
            names.add( s.getName() );
        }
        return names;
    }

    public OneshotSample getOneshot(int idx) {
        if( idx >= 0 && idx < oneshot.size() ) {
            return oneshot.get(idx);
        }
        return null;
    }

    public List<RealtimeSample> getRealtime() {
        return realtime;
    }

    public List<String> getRealtimeNames() {
        final List<String> names = new ArrayList<>();
        for(RealtimeSample s : realtime) {
            names.add( s.getName() );
        }
        return names;
    }

    public RealtimeSample getRealtime(int idx) {
        if( idx >= 0 && idx < realtime.size() ) {
            return realtime.get(idx);
        }
        return null;
    }

    public List<CalibrationSample> getCalibration() {
        return calibration;
    }

    public List<String> getCalibrationNames() {
        final List<String> names = new ArrayList<>();
        for(CalibrationSample s : calibration) {
            names.add( s.getName() );
        }
        return names;
    }

    public CalibrationSample getCalibration(int idx) {
        if( idx >= 0 && idx < calibration.size() ) {
            return calibration.get(idx);
        }
        return null;
    }

    private void refresh() {
        oneshot.clear();
        realtime.clear();
        calibration.clear();

        final List<JSONObject> oneshotObjects = getJsonObjects("oneshot");
        for(JSONObject json : oneshotObjects) {
            final OneshotSample sample = OneshotSample.create(json);
            if( sample != null ) {
                oneshot.add(sample);
            }
        }

        final List<JSONObject> realtimeObjects = getJsonObjects("realtime");
        for(JSONObject json : realtimeObjects) {
            final RealtimeSample sample = RealtimeSample.create(json);
            if( sample != null ) {
                realtime.add(sample);
            }
        }

        final List<JSONObject> calibrationObjects = getJsonObjects("calibration");
        for(JSONObject json : calibrationObjects) {
            final CalibrationSample sample = CalibrationSample.create(json);
            if( sample != null ) {
                calibration.add(sample);
            }
        }
    }

    private File[] getFiles(String sub) {
        final File oneshotDir = new File(context.getFilesDir(),sub);
        File[] files = oneshotDir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return ( name.endsWith(".json") );
            }
        });
        return files;
    }

    private List<JSONObject> getJsonObjects(String sub) {
        List<JSONObject> jsons = new ArrayList<>();
        File[] files = getFiles(sub);
        if( files != null ) {
            for(File f : files) {
                JSONObject json = readFile(f);
                if( json != null ) {
                    jsons.add(json);
                }
            }
        }
        return jsons;
    }

    private JSONObject readFile(File file) {
        try {
            final InputStream in = new FileInputStream(file);
            final StringBuilder sb = new StringBuilder();
            try(BufferedReader br = new BufferedReader(new InputStreamReader(in)) ) {
                for(String line; (line = br.readLine()) != null; ) {
                    sb.append(line).append("\n");
                }
            }
            return JSONObject.parseObject(sb.toString());
        } catch (IOException | JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
}
